package com.rongzhong.routing.main;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;

import org.hibernate.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.rongzhong.routing.check.AbortCheck;
import com.rongzhong.routing.check.BaseCheck;
import com.rongzhong.routing.check.BinLogCheck;
import com.rongzhong.routing.check.BytesCheck;
import com.rongzhong.routing.check.DMLCheck;
import com.rongzhong.routing.check.DataCheck;
import com.rongzhong.routing.check.InnodbPoolCheck;
import com.rongzhong.routing.check.LockCheck;
import com.rongzhong.routing.check.MaxConnectionsCheck;
import com.rongzhong.routing.check.QueryCacheCheck;
import com.rongzhong.routing.check.SelectHandlerCheck;
import com.rongzhong.routing.check.SlowQueryCheck;
import com.rongzhong.routing.check.TableCacheCheck;
import com.rongzhong.routing.check.TaskCheck;
import com.rongzhong.routing.check.ThreadCheck;
import com.rongzhong.routing.check.TmpTableCheck;
import com.rongzhong.routing.hibernate.HibernateUtil;
import com.rongzhong.routing.util.PerformanceUtil;


/**
 * 
 * @author longxuegang@gmail.com
 * @version 1.0 2011-9-22
 * @since 1.0
 * @see
 */

public class RoutingInspecte {
	private HibernateUtil hibernate = HibernateUtil.getInstance();
	private PerformanceUtil perfUtil = PerformanceUtil.getInstance();
	private final int dbCheckNumber = perfUtil.getDbCheckNumber(); //3
	private final Map<Integer, Map<String,String>> valuesMap = new HashMap<Integer, Map<String,String>>();
	private final Map<Integer, Map<String,String>> variablesMap = new HashMap<Integer, Map<String,String>>();
	private static final Logger log = LoggerFactory.getLogger(RoutingInspecte.class);
	private static RoutingInspecte instance = new RoutingInspecte();
	
	private RoutingInspecte(){
		init();
	}

	private void init() {
		checkOutAllDatabaseNode();
		showVariablesAllDatabaseNode();
	}
	
	public static RoutingInspecte getInstance(){
		return instance;
	}
	
	public Map<Integer, Map<String,String>> getValuesMap(){
		return valuesMap;
	}
	
	public Map<Integer, Map<String,String>> getVariablesMap(){
		return variablesMap;
	}
	
	public void checkOutAllDatabaseNode(){
		if (dbCheckNumber <= 0) {
			log.error("No databaseNode can be checked. dbNumber : {}",dbCheckNumber);
			return;
		}
		for (int dbIndex = 0; dbIndex < dbCheckNumber; dbIndex++) {
			checkOutDatabaseNode(dbIndex);
		}
	}
	
	public void showVariablesAllDatabaseNode(){
		if (dbCheckNumber <= 0) {
			log.error("No databaseNode can be checked. dbNumber : {}",dbCheckNumber);
			return;
		}
		for (int dbIndex = 0; dbIndex < dbCheckNumber; dbIndex++) {
			showVariablesDatabaseNode(dbIndex);
		}
	}
	
	private void showVariablesDatabaseNode(int dbIndex) {
		Session session = hibernate.currentSession(dbIndex);
		Connection conn = null;
		Statement state = null;
		ResultSet rsSet = null;
		try {
			String sql = "show variables";
			conn = session.connection();
			state = conn.createStatement();
			rsSet = state.executeQuery(sql);
			String variables = "";
			String value = "";
			Map<String,String> map = new HashMap<String, String>();
			while (rsSet.next()) {
				variables = rsSet.getString("Variable_name");
				value = rsSet.getString("Value");
				map.put(variables, value);
			}
			variablesMap.put(dbIndex, map);
		} catch (SQLException e) {
			log.error("showVariablesDatabaseNode run into error." ,e);
		}finally{
			hibernate.closeSession(session);
		}
	}

	public void checkOutDatabaseNode(int dbIndex){
		Session session = hibernate.currentSession(dbIndex);
		Connection conn = null;
		Statement state = null;
		ResultSet rsSet = null;
		try {
			String sql = "show global status";
			conn = session.connection();
			state = conn.createStatement();
			rsSet = state.executeQuery(sql);
			String variables = "";
			String value = "";
			Map<String,String> map = new HashMap<String, String>();
			while (rsSet.next()) {
				variables = rsSet.getString("Variable_name");
				value = rsSet.getString("Value");
				map.put(variables, value);
			}
			valuesMap.put(dbIndex, map);
		} catch (SQLException e) {
			log.error("checkOutDatabaseNode run into error." ,e);
		}finally{
			hibernate.closeSession(session);
		}
	}
	
	public void checkOut(){
		new TaskCheck().checkOutTasks();
		new BaseCheck().checkOutBase();
		new DataCheck().checkOutData();
		new BytesCheck().checkOutBytes();
		new AbortCheck().checkOutAborts();
		new ThreadCheck().checkOutThread();
		new LockCheck().checkOutLock();
		new QueryCacheCheck().checkOutQueryCache();
		new MaxConnectionsCheck().checkOutMaxConnections();
		new TableCacheCheck().checkOutTableCache();
		new TmpTableCheck().checkOutTmpTable();
		new SlowQueryCheck().checkOutSlowQuery();
		new SelectHandlerCheck().checkOutSelectHandler();
		new InnodbPoolCheck().checkOutInnodbPool();
		new DMLCheck().checkOutDML();
		new BinLogCheck().checkOutBinLog();
	}

	public static void main(String[] args) {
		RoutingInspecte.getInstance().checkOut();
	}
}
